//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension CloudHSMV2 {
    // MARK: Enums

    public enum BackupPolicy: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case `default` = "DEFAULT"
        public var description: String { return self.rawValue }
    }

    public enum BackupRetentionType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case days = "DAYS"
        public var description: String { return self.rawValue }
    }

    public enum BackupState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case createInProgress = "CREATE_IN_PROGRESS"
        case deleted = "DELETED"
        case pendingDeletion = "PENDING_DELETION"
        case ready = "READY"
        public var description: String { return self.rawValue }
    }

    public enum ClusterMode: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case fips = "FIPS"
        case nonFips = "NON_FIPS"
        public var description: String { return self.rawValue }
    }

    public enum ClusterState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "ACTIVE"
        case createInProgress = "CREATE_IN_PROGRESS"
        case degraded = "DEGRADED"
        case deleteInProgress = "DELETE_IN_PROGRESS"
        case deleted = "DELETED"
        case initializeInProgress = "INITIALIZE_IN_PROGRESS"
        case initialized = "INITIALIZED"
        case modifyInProgress = "MODIFY_IN_PROGRESS"
        case rollbackInProgress = "ROLLBACK_IN_PROGRESS"
        case uninitialized = "UNINITIALIZED"
        case updateInProgress = "UPDATE_IN_PROGRESS"
        public var description: String { return self.rawValue }
    }

    public enum HsmState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "ACTIVE"
        case createInProgress = "CREATE_IN_PROGRESS"
        case degraded = "DEGRADED"
        case deleteInProgress = "DELETE_IN_PROGRESS"
        case deleted = "DELETED"
        public var description: String { return self.rawValue }
    }

    public enum NetworkType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case dualstack = "DUALSTACK"
        case ipv4 = "IPV4"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct Backup: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the backup.
        public let backupArn: String?
        /// The identifier (ID) of the backup.
        public let backupId: String
        /// The state of the backup.
        public let backupState: BackupState?
        /// The identifier (ID) of the cluster that was backed up.
        public let clusterId: String?
        /// The date and time when the backup was copied from a source backup.
        public let copyTimestamp: Date?
        /// The date and time when the backup was created.
        public let createTimestamp: Date?
        /// The date and time when the backup will be permanently deleted.
        public let deleteTimestamp: Date?
        /// The HSM type used to create the backup.
        public let hsmType: String?
        /// The mode of the cluster that was backed up.
        public let mode: ClusterMode?
        /// Specifies whether the service should exempt a backup from the retention policy for the cluster. True exempts  a backup from the retention policy. False means the service applies the backup retention policy defined at the cluster.
        public let neverExpires: Bool?
        /// The identifier (ID) of the source backup from which the new backup was copied.
        public let sourceBackup: String?
        /// The identifier (ID) of the cluster containing the source backup from which the new backup was copied.
        public let sourceCluster: String?
        /// The AWS Region that contains the source backup from which the new backup was copied.
        public let sourceRegion: String?
        /// The list of tags for the backup.
        public let tagList: [Tag]?

        @inlinable
        public init(backupArn: String? = nil, backupId: String, backupState: BackupState? = nil, clusterId: String? = nil, copyTimestamp: Date? = nil, createTimestamp: Date? = nil, deleteTimestamp: Date? = nil, hsmType: String? = nil, mode: ClusterMode? = nil, neverExpires: Bool? = nil, sourceBackup: String? = nil, sourceCluster: String? = nil, sourceRegion: String? = nil, tagList: [Tag]? = nil) {
            self.backupArn = backupArn
            self.backupId = backupId
            self.backupState = backupState
            self.clusterId = clusterId
            self.copyTimestamp = copyTimestamp
            self.createTimestamp = createTimestamp
            self.deleteTimestamp = deleteTimestamp
            self.hsmType = hsmType
            self.mode = mode
            self.neverExpires = neverExpires
            self.sourceBackup = sourceBackup
            self.sourceCluster = sourceCluster
            self.sourceRegion = sourceRegion
            self.tagList = tagList
        }

        private enum CodingKeys: String, CodingKey {
            case backupArn = "BackupArn"
            case backupId = "BackupId"
            case backupState = "BackupState"
            case clusterId = "ClusterId"
            case copyTimestamp = "CopyTimestamp"
            case createTimestamp = "CreateTimestamp"
            case deleteTimestamp = "DeleteTimestamp"
            case hsmType = "HsmType"
            case mode = "Mode"
            case neverExpires = "NeverExpires"
            case sourceBackup = "SourceBackup"
            case sourceCluster = "SourceCluster"
            case sourceRegion = "SourceRegion"
            case tagList = "TagList"
        }
    }

    public struct BackupRetentionPolicy: AWSEncodableShape & AWSDecodableShape {
        /// The type of backup retention policy. For the DAYS type, the value is  the number of days to retain backups.
        public let type: BackupRetentionType?
        /// Use a value between 7 - 379.
        public let value: String?

        @inlinable
        public init(type: BackupRetentionType? = nil, value: String? = nil) {
            self.type = type
            self.value = value
        }

        public func validate(name: String) throws {
            try self.validate(self.value, name: "value", parent: name, max: 3)
            try self.validate(self.value, name: "value", parent: name, min: 1)
            try self.validate(self.value, name: "value", parent: name, pattern: "^[0-9]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case type = "Type"
            case value = "Value"
        }
    }

    public struct Certificates: AWSDecodableShape {
        /// The HSM hardware certificate issued (signed) by CloudHSM.
        public let awsHardwareCertificate: String?
        /// The cluster certificate issued (signed) by the issuing certificate authority (CA) of the cluster's owner.
        public let clusterCertificate: String?
        /// The cluster's certificate signing request (CSR). The CSR exists only when the cluster's state is UNINITIALIZED.
        public let clusterCsr: String?
        /// The HSM certificate issued (signed) by the HSM hardware.
        public let hsmCertificate: String?
        /// The HSM hardware certificate issued (signed) by the hardware manufacturer.
        public let manufacturerHardwareCertificate: String?

        @inlinable
        public init(awsHardwareCertificate: String? = nil, clusterCertificate: String? = nil, clusterCsr: String? = nil, hsmCertificate: String? = nil, manufacturerHardwareCertificate: String? = nil) {
            self.awsHardwareCertificate = awsHardwareCertificate
            self.clusterCertificate = clusterCertificate
            self.clusterCsr = clusterCsr
            self.hsmCertificate = hsmCertificate
            self.manufacturerHardwareCertificate = manufacturerHardwareCertificate
        }

        private enum CodingKeys: String, CodingKey {
            case awsHardwareCertificate = "AwsHardwareCertificate"
            case clusterCertificate = "ClusterCertificate"
            case clusterCsr = "ClusterCsr"
            case hsmCertificate = "HsmCertificate"
            case manufacturerHardwareCertificate = "ManufacturerHardwareCertificate"
        }
    }

    public struct Cluster: AWSDecodableShape {
        /// The cluster's backup policy.
        public let backupPolicy: BackupPolicy?
        /// A policy that defines how the service retains backups.
        public let backupRetentionPolicy: BackupRetentionPolicy?
        /// Contains one or more certificates or a certificate signing request (CSR).
        public let certificates: Certificates?
        /// The cluster's identifier (ID).
        public let clusterId: String?
        /// The date and time when the cluster was created.
        public let createTimestamp: Date?
        /// Contains information about the HSMs in the cluster.
        public let hsms: [Hsm]?
        /// The type of HSM that the cluster contains.
        public let hsmType: String?
        /// The timestamp until when the cluster can be rolled back to its original HSM type.
        public let hsmTypeRollbackExpiration: Date?
        /// The mode of the cluster.
        public let mode: ClusterMode?
        /// The cluster's NetworkType can be IPv4 (the default) or DUALSTACK. The IPv4 NetworkType restricts communication between your application and the hardware security modules (HSMs) to the IPv4 protocol only. The DUALSTACK NetworkType enables communication over both IPv4 and IPv6 protocols. To use DUALSTACK, configure your virtual private cloud (VPC) and subnets to support both IPv4 and IPv6. This configuration involves adding IPv6 Classless Inter-Domain Routing (CIDR) blocks to the existing IPv4 CIDR blocks in your subnets. The NetworkType you choose affects the network addressing options for your cluster. DUALSTACK provides more flexibility by supporting both IPv4 and IPv6 communication.
        public let networkType: NetworkType?
        /// The default password for the cluster's Pre-Crypto Officer (PRECO) user.
        public let preCoPassword: String?
        /// The identifier (ID) of the cluster's security group.
        public let securityGroup: String?
        /// The identifier (ID) of the backup used to create the cluster. This value exists only when the cluster was created from a backup.
        public let sourceBackupId: String?
        /// The cluster's state.
        public let state: ClusterState?
        /// A description of the cluster's state.
        public let stateMessage: String?
        /// A map from availability zone to the cluster’s subnet in that availability zone.
        public let subnetMapping: [String: String]?
        /// The list of tags for the cluster.
        public let tagList: [Tag]?
        /// The identifier (ID) of the virtual private cloud (VPC) that contains the cluster.
        public let vpcId: String?

        @inlinable
        public init(backupPolicy: BackupPolicy? = nil, backupRetentionPolicy: BackupRetentionPolicy? = nil, certificates: Certificates? = nil, clusterId: String? = nil, createTimestamp: Date? = nil, hsms: [Hsm]? = nil, hsmType: String? = nil, hsmTypeRollbackExpiration: Date? = nil, mode: ClusterMode? = nil, networkType: NetworkType? = nil, preCoPassword: String? = nil, securityGroup: String? = nil, sourceBackupId: String? = nil, state: ClusterState? = nil, stateMessage: String? = nil, subnetMapping: [String: String]? = nil, tagList: [Tag]? = nil, vpcId: String? = nil) {
            self.backupPolicy = backupPolicy
            self.backupRetentionPolicy = backupRetentionPolicy
            self.certificates = certificates
            self.clusterId = clusterId
            self.createTimestamp = createTimestamp
            self.hsms = hsms
            self.hsmType = hsmType
            self.hsmTypeRollbackExpiration = hsmTypeRollbackExpiration
            self.mode = mode
            self.networkType = networkType
            self.preCoPassword = preCoPassword
            self.securityGroup = securityGroup
            self.sourceBackupId = sourceBackupId
            self.state = state
            self.stateMessage = stateMessage
            self.subnetMapping = subnetMapping
            self.tagList = tagList
            self.vpcId = vpcId
        }

        private enum CodingKeys: String, CodingKey {
            case backupPolicy = "BackupPolicy"
            case backupRetentionPolicy = "BackupRetentionPolicy"
            case certificates = "Certificates"
            case clusterId = "ClusterId"
            case createTimestamp = "CreateTimestamp"
            case hsms = "Hsms"
            case hsmType = "HsmType"
            case hsmTypeRollbackExpiration = "HsmTypeRollbackExpiration"
            case mode = "Mode"
            case networkType = "NetworkType"
            case preCoPassword = "PreCoPassword"
            case securityGroup = "SecurityGroup"
            case sourceBackupId = "SourceBackupId"
            case state = "State"
            case stateMessage = "StateMessage"
            case subnetMapping = "SubnetMapping"
            case tagList = "TagList"
            case vpcId = "VpcId"
        }
    }

    public struct CopyBackupToRegionRequest: AWSEncodableShape {
        /// The ID of the backup that will be copied to the destination region.
        public let backupId: String
        /// The AWS region that will contain your copied CloudHSM cluster backup.
        public let destinationRegion: String
        /// Tags to apply to the destination backup during creation. If you specify tags, only these tags will be applied to the destination backup. If you do not specify tags, the service copies tags from the source backup to the destination backup.
        public let tagList: [Tag]?

        @inlinable
        public init(backupId: String, destinationRegion: String, tagList: [Tag]? = nil) {
            self.backupId = backupId
            self.destinationRegion = destinationRegion
            self.tagList = tagList
        }

        public func validate(name: String) throws {
            try self.validate(self.backupId, name: "backupId", parent: name, pattern: "^backup-[2-7a-zA-Z]{11,16}$")
            try self.validate(self.destinationRegion, name: "destinationRegion", parent: name, pattern: "^[a-z]{2}(-(gov))?-(east|west|north|south|central){1,2}-\\d$")
            try self.tagList?.forEach {
                try $0.validate(name: "\(name).tagList[]")
            }
            try self.validate(self.tagList, name: "tagList", parent: name, max: 50)
            try self.validate(self.tagList, name: "tagList", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case backupId = "BackupId"
            case destinationRegion = "DestinationRegion"
            case tagList = "TagList"
        }
    }

    public struct CopyBackupToRegionResponse: AWSDecodableShape {
        /// Information on the backup that will be copied to the destination region, including CreateTimestamp, SourceBackup, SourceCluster, and Source Region. CreateTimestamp of the destination backup will be the same as that of the source backup. You will need to use the sourceBackupID returned in this operation to use the DescribeBackups operation on the backup that will be copied to the destination region.
        public let destinationBackup: DestinationBackup?

        @inlinable
        public init(destinationBackup: DestinationBackup? = nil) {
            self.destinationBackup = destinationBackup
        }

        private enum CodingKeys: String, CodingKey {
            case destinationBackup = "DestinationBackup"
        }
    }

    public struct CreateClusterRequest: AWSEncodableShape {
        /// A policy that defines how the service retains backups.
        public let backupRetentionPolicy: BackupRetentionPolicy?
        /// The type of HSM to use in the cluster. The allowed values are hsm1.medium and hsm2m.medium.
        public let hsmType: String
        /// The mode to use in the cluster. The allowed values are FIPS and NON_FIPS.
        public let mode: ClusterMode?
        /// The NetworkType to create a cluster with. The allowed values are IPV4 and DUALSTACK.
        public let networkType: NetworkType?
        /// The identifier (ID) or the Amazon Resource Name (ARN) of the cluster backup to restore. Use this value to restore the cluster from a backup instead of creating a new cluster. To find the backup ID or ARN, use DescribeBackups. If using a backup in another account, the full ARN must be supplied.
        public let sourceBackupId: String?
        /// The identifiers (IDs) of the subnets where you are creating the cluster. You must specify at least one subnet. If you specify multiple subnets, they must meet the following criteria:   All subnets must be in the same virtual private cloud (VPC).   You can specify only one subnet per Availability Zone.
        public let subnetIds: [String]
        /// Tags to apply to the CloudHSM cluster during creation.
        public let tagList: [Tag]?

        @inlinable
        public init(backupRetentionPolicy: BackupRetentionPolicy? = nil, hsmType: String, mode: ClusterMode? = nil, networkType: NetworkType? = nil, sourceBackupId: String? = nil, subnetIds: [String], tagList: [Tag]? = nil) {
            self.backupRetentionPolicy = backupRetentionPolicy
            self.hsmType = hsmType
            self.mode = mode
            self.networkType = networkType
            self.sourceBackupId = sourceBackupId
            self.subnetIds = subnetIds
            self.tagList = tagList
        }

        public func validate(name: String) throws {
            try self.backupRetentionPolicy?.validate(name: "\(name).backupRetentionPolicy")
            try self.validate(self.hsmType, name: "hsmType", parent: name, max: 32)
            try self.validate(self.hsmType, name: "hsmType", parent: name, pattern: "^((p|)hsm[0-9][a-z.]*\\.[a-zA-Z]+)$")
            try self.validate(self.sourceBackupId, name: "sourceBackupId", parent: name, pattern: "^(arn:aws(-(us-gov))?:cloudhsm:([a-z]{2}(-(gov|isob|iso))?-(east|west|north|south|central){1,2}-[0-9]{1}):[0-9]{12}:backup/)?backup-[2-7a-zA-Z]{11,16}$")
            try self.subnetIds.forEach {
                try validate($0, name: "subnetIds[]", parent: name, pattern: "^subnet-[0-9a-fA-F]{8,17}$")
            }
            try self.validate(self.subnetIds, name: "subnetIds", parent: name, max: 10)
            try self.validate(self.subnetIds, name: "subnetIds", parent: name, min: 1)
            try self.tagList?.forEach {
                try $0.validate(name: "\(name).tagList[]")
            }
            try self.validate(self.tagList, name: "tagList", parent: name, max: 50)
            try self.validate(self.tagList, name: "tagList", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case backupRetentionPolicy = "BackupRetentionPolicy"
            case hsmType = "HsmType"
            case mode = "Mode"
            case networkType = "NetworkType"
            case sourceBackupId = "SourceBackupId"
            case subnetIds = "SubnetIds"
            case tagList = "TagList"
        }
    }

    public struct CreateClusterResponse: AWSDecodableShape {
        /// Information about the cluster that was created.
        public let cluster: Cluster?

        @inlinable
        public init(cluster: Cluster? = nil) {
            self.cluster = cluster
        }

        private enum CodingKeys: String, CodingKey {
            case cluster = "Cluster"
        }
    }

    public struct CreateHsmRequest: AWSEncodableShape {
        /// The Availability Zone where you are creating the HSM. To find the cluster's Availability Zones, use DescribeClusters.
        public let availabilityZone: String
        /// The identifier (ID) of the HSM's cluster. To find the cluster ID, use DescribeClusters.
        public let clusterId: String
        /// The HSM's IP address. If you specify an IP address, use an available address from the subnet that maps to the Availability Zone where you are creating the HSM. If you don't specify an IP address, one is chosen for you from that subnet.
        public let ipAddress: String?

        @inlinable
        public init(availabilityZone: String, clusterId: String, ipAddress: String? = nil) {
            self.availabilityZone = availabilityZone
            self.clusterId = clusterId
            self.ipAddress = ipAddress
        }

        public func validate(name: String) throws {
            try self.validate(self.availabilityZone, name: "availabilityZone", parent: name, pattern: "^[a-z]{2}(-(gov))?-(east|west|north|south|central){1,2}-\\d[a-z]$")
            try self.validate(self.clusterId, name: "clusterId", parent: name, pattern: "^cluster-[2-7a-zA-Z]{11,16}$")
            try self.validate(self.ipAddress, name: "ipAddress", parent: name, pattern: "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$")
        }

        private enum CodingKeys: String, CodingKey {
            case availabilityZone = "AvailabilityZone"
            case clusterId = "ClusterId"
            case ipAddress = "IpAddress"
        }
    }

    public struct CreateHsmResponse: AWSDecodableShape {
        /// Information about the HSM that was created.
        public let hsm: Hsm?

        @inlinable
        public init(hsm: Hsm? = nil) {
            self.hsm = hsm
        }

        private enum CodingKeys: String, CodingKey {
            case hsm = "Hsm"
        }
    }

    public struct DeleteBackupRequest: AWSEncodableShape {
        /// The ID of the backup to be deleted. To find the ID of a backup, use the DescribeBackups operation.
        public let backupId: String

        @inlinable
        public init(backupId: String) {
            self.backupId = backupId
        }

        public func validate(name: String) throws {
            try self.validate(self.backupId, name: "backupId", parent: name, pattern: "^backup-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case backupId = "BackupId"
        }
    }

    public struct DeleteBackupResponse: AWSDecodableShape {
        /// Information on the Backup object deleted.
        public let backup: Backup?

        @inlinable
        public init(backup: Backup? = nil) {
            self.backup = backup
        }

        private enum CodingKeys: String, CodingKey {
            case backup = "Backup"
        }
    }

    public struct DeleteClusterRequest: AWSEncodableShape {
        /// The identifier (ID) of the cluster that you are deleting. To find the cluster ID, use DescribeClusters.
        public let clusterId: String

        @inlinable
        public init(clusterId: String) {
            self.clusterId = clusterId
        }

        public func validate(name: String) throws {
            try self.validate(self.clusterId, name: "clusterId", parent: name, pattern: "^cluster-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case clusterId = "ClusterId"
        }
    }

    public struct DeleteClusterResponse: AWSDecodableShape {
        /// Information about the cluster that was deleted.
        public let cluster: Cluster?

        @inlinable
        public init(cluster: Cluster? = nil) {
            self.cluster = cluster
        }

        private enum CodingKeys: String, CodingKey {
            case cluster = "Cluster"
        }
    }

    public struct DeleteHsmRequest: AWSEncodableShape {
        /// The identifier (ID) of the cluster that contains the HSM that you are deleting.
        public let clusterId: String
        /// The identifier (ID) of the elastic network interface (ENI) of the HSM that you are deleting.
        public let eniId: String?
        /// The IP address of the elastic network interface (ENI) of the HSM that you are deleting.
        public let eniIp: String?
        /// The identifier (ID) of the HSM that you are deleting.
        public let hsmId: String?

        @inlinable
        public init(clusterId: String, eniId: String? = nil, eniIp: String? = nil, hsmId: String? = nil) {
            self.clusterId = clusterId
            self.eniId = eniId
            self.eniIp = eniIp
            self.hsmId = hsmId
        }

        public func validate(name: String) throws {
            try self.validate(self.clusterId, name: "clusterId", parent: name, pattern: "^cluster-[2-7a-zA-Z]{11,16}$")
            try self.validate(self.eniId, name: "eniId", parent: name, pattern: "^eni-[0-9a-fA-F]{8,17}$")
            try self.validate(self.eniIp, name: "eniIp", parent: name, pattern: "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$")
            try self.validate(self.hsmId, name: "hsmId", parent: name, pattern: "^hsm-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case clusterId = "ClusterId"
            case eniId = "EniId"
            case eniIp = "EniIp"
            case hsmId = "HsmId"
        }
    }

    public struct DeleteHsmResponse: AWSDecodableShape {
        /// The identifier (ID) of the HSM that was deleted.
        public let hsmId: String?

        @inlinable
        public init(hsmId: String? = nil) {
            self.hsmId = hsmId
        }

        private enum CodingKeys: String, CodingKey {
            case hsmId = "HsmId"
        }
    }

    public struct DeleteResourcePolicyRequest: AWSEncodableShape {
        /// Amazon Resource Name (ARN) of the resource from which the policy will be removed.
        public let resourceArn: String?

        @inlinable
        public init(resourceArn: String? = nil) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws(-(us-gov))?:cloudhsm:([a-z]{2}(-(gov|isob|iso))?-(east|west|north|south|central){1,2}-[0-9]{1}):[0-9]{12}:(backup/backup|cluster/cluster|hsm/hsm)-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case resourceArn = "ResourceArn"
        }
    }

    public struct DeleteResourcePolicyResponse: AWSDecodableShape {
        /// The policy previously attached to the resource.
        public let policy: String?
        /// Amazon Resource Name (ARN) of the resource from which the policy was deleted.
        public let resourceArn: String?

        @inlinable
        public init(policy: String? = nil, resourceArn: String? = nil) {
            self.policy = policy
            self.resourceArn = resourceArn
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case resourceArn = "ResourceArn"
        }
    }

    public struct DescribeBackupsRequest: AWSEncodableShape {
        /// One or more filters to limit the items returned in the response. Use the backupIds filter to return only the specified backups. Specify backups by their backup identifier (ID). Use the sourceBackupIds filter to return only the backups created from a source backup. The sourceBackupID of a source backup is returned by the CopyBackupToRegion operation. Use the clusterIds filter to return only the backups for the specified clusters. Specify clusters by their cluster identifier (ID). Use the states filter to return only backups that match the specified state. Use the neverExpires filter to return backups filtered by the value in the neverExpires parameter. True returns all backups exempt from the backup retention policy. False returns all backups with a backup retention policy defined at the cluster.
        public let filters: [String: [String]]?
        /// The maximum number of backups to return in the response. When there are more backups than the number you specify, the response contains a NextToken value.
        public let maxResults: Int?
        /// The NextToken value that you received in the previous response. Use this value to get more backups.
        public let nextToken: String?
        /// Describe backups that are shared with you.  By default when using this option, the command returns backups that have been shared using a standard Resource Access Manager  resource share. In order for a backup that was shared using the PutResourcePolicy command to be returned, the share must be promoted to a  standard resource share using the RAM PromoteResourceShareCreatedFromPolicy API operation.
        ///  For more information about sharing backups, see  Working with shared backups in the CloudHSM User Guide.
        public let shared: Bool?
        /// Designates whether or not to sort the return backups by ascending chronological order of generation.
        public let sortAscending: Bool?

        @inlinable
        public init(filters: [String: [String]]? = nil, maxResults: Int? = nil, nextToken: String? = nil, shared: Bool? = nil, sortAscending: Bool? = nil) {
            self.filters = filters
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.shared = shared
            self.sortAscending = sortAscending
        }

        public func validate(name: String) throws {
            try self.filters?.forEach {
                try validate($0.key, name: "filters.key", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            }
            try self.validate(self.filters, name: "filters", parent: name, max: 30)
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 50)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 256)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: ".*")
        }

        private enum CodingKeys: String, CodingKey {
            case filters = "Filters"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case shared = "Shared"
            case sortAscending = "SortAscending"
        }
    }

    public struct DescribeBackupsResponse: AWSDecodableShape {
        /// A list of backups.
        public let backups: [Backup]?
        /// An opaque string that indicates that the response contains only a subset of backups. Use this value in a subsequent DescribeBackups request to get more backups.
        public let nextToken: String?

        @inlinable
        public init(backups: [Backup]? = nil, nextToken: String? = nil) {
            self.backups = backups
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case backups = "Backups"
            case nextToken = "NextToken"
        }
    }

    public struct DescribeClustersRequest: AWSEncodableShape {
        /// One or more filters to limit the items returned in the response. Use the clusterIds filter to return only the specified clusters. Specify clusters by their cluster identifier (ID). Use the vpcIds filter to return only the clusters in the specified virtual private clouds (VPCs). Specify VPCs by their VPC identifier (ID). Use the states filter to return only clusters that match the specified state.
        public let filters: [String: [String]]?
        /// The maximum number of clusters to return in the response. When there are more clusters than the number you specify, the response contains a NextToken value.
        public let maxResults: Int?
        /// The NextToken value that you received in the previous response. Use this value to get more clusters.
        public let nextToken: String?

        @inlinable
        public init(filters: [String: [String]]? = nil, maxResults: Int? = nil, nextToken: String? = nil) {
            self.filters = filters
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.filters?.forEach {
                try validate($0.key, name: "filters.key", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            }
            try self.validate(self.filters, name: "filters", parent: name, max: 30)
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 25)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 256)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: ".*")
        }

        private enum CodingKeys: String, CodingKey {
            case filters = "Filters"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct DescribeClustersResponse: AWSDecodableShape {
        /// A list of clusters.
        public let clusters: [Cluster]?
        /// An opaque string that indicates that the response contains only a subset of clusters. Use this value in a subsequent DescribeClusters request to get more clusters.
        public let nextToken: String?

        @inlinable
        public init(clusters: [Cluster]? = nil, nextToken: String? = nil) {
            self.clusters = clusters
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case clusters = "Clusters"
            case nextToken = "NextToken"
        }
    }

    public struct DestinationBackup: AWSDecodableShape {
        /// The date and time when both the source backup was created.
        public let createTimestamp: Date?
        /// The identifier (ID) of the source backup from which the new backup was copied.
        public let sourceBackup: String?
        /// The identifier (ID) of the cluster containing the source backup from which the new backup was copied.
        public let sourceCluster: String?
        /// The AWS region that contains the source backup from which the new backup was copied.
        public let sourceRegion: String?

        @inlinable
        public init(createTimestamp: Date? = nil, sourceBackup: String? = nil, sourceCluster: String? = nil, sourceRegion: String? = nil) {
            self.createTimestamp = createTimestamp
            self.sourceBackup = sourceBackup
            self.sourceCluster = sourceCluster
            self.sourceRegion = sourceRegion
        }

        private enum CodingKeys: String, CodingKey {
            case createTimestamp = "CreateTimestamp"
            case sourceBackup = "SourceBackup"
            case sourceCluster = "SourceCluster"
            case sourceRegion = "SourceRegion"
        }
    }

    public struct GetResourcePolicyRequest: AWSEncodableShape {
        /// Amazon Resource Name (ARN) of the resource to which a policy is attached.
        public let resourceArn: String?

        @inlinable
        public init(resourceArn: String? = nil) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws(-(us-gov))?:cloudhsm:([a-z]{2}(-(gov|isob|iso))?-(east|west|north|south|central){1,2}-[0-9]{1}):[0-9]{12}:(backup/backup|cluster/cluster|hsm/hsm)-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case resourceArn = "ResourceArn"
        }
    }

    public struct GetResourcePolicyResponse: AWSDecodableShape {
        /// The policy attached to a resource.
        public let policy: String?

        @inlinable
        public init(policy: String? = nil) {
            self.policy = policy
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
        }
    }

    public struct Hsm: AWSDecodableShape {
        /// The Availability Zone that contains the HSM.
        public let availabilityZone: String?
        /// The identifier (ID) of the cluster that contains the HSM.
        public let clusterId: String?
        /// The identifier (ID) of the HSM's elastic network interface (ENI).
        public let eniId: String?
        /// The IP address of the HSM's elastic network interface (ENI).
        public let eniIp: String?
        /// The IPv6 address (if any) of the HSM's elastic network interface (ENI).
        public let eniIpV6: String?
        /// The HSM's identifier (ID).
        public let hsmId: String
        /// The type of HSM.
        public let hsmType: String?
        /// The HSM's state.
        public let state: HsmState?
        /// A description of the HSM's state.
        public let stateMessage: String?
        /// The subnet that contains the HSM's elastic network interface (ENI).
        public let subnetId: String?

        @inlinable
        public init(availabilityZone: String? = nil, clusterId: String? = nil, eniId: String? = nil, eniIp: String? = nil, eniIpV6: String? = nil, hsmId: String, hsmType: String? = nil, state: HsmState? = nil, stateMessage: String? = nil, subnetId: String? = nil) {
            self.availabilityZone = availabilityZone
            self.clusterId = clusterId
            self.eniId = eniId
            self.eniIp = eniIp
            self.eniIpV6 = eniIpV6
            self.hsmId = hsmId
            self.hsmType = hsmType
            self.state = state
            self.stateMessage = stateMessage
            self.subnetId = subnetId
        }

        private enum CodingKeys: String, CodingKey {
            case availabilityZone = "AvailabilityZone"
            case clusterId = "ClusterId"
            case eniId = "EniId"
            case eniIp = "EniIp"
            case eniIpV6 = "EniIpV6"
            case hsmId = "HsmId"
            case hsmType = "HsmType"
            case state = "State"
            case stateMessage = "StateMessage"
            case subnetId = "SubnetId"
        }
    }

    public struct InitializeClusterRequest: AWSEncodableShape {
        /// The identifier (ID) of the cluster that you are claiming. To find the cluster ID, use DescribeClusters.
        public let clusterId: String
        /// The cluster certificate issued (signed) by your issuing certificate authority (CA). The certificate must be in PEM format and can contain a maximum of 5000 characters.
        public let signedCert: String
        /// The issuing certificate of the issuing certificate authority (CA) that issued (signed) the cluster certificate. You must use a self-signed certificate. The certificate used to sign the HSM CSR must be directly available, and thus must be the root certificate. The certificate must be in PEM format and can contain a maximum of 5000 characters.
        public let trustAnchor: String

        @inlinable
        public init(clusterId: String, signedCert: String, trustAnchor: String) {
            self.clusterId = clusterId
            self.signedCert = signedCert
            self.trustAnchor = trustAnchor
        }

        public func validate(name: String) throws {
            try self.validate(self.clusterId, name: "clusterId", parent: name, pattern: "^cluster-[2-7a-zA-Z]{11,16}$")
            try self.validate(self.signedCert, name: "signedCert", parent: name, max: 20000)
            try self.validate(self.signedCert, name: "signedCert", parent: name, pattern: "^[a-zA-Z0-9+-/=\\s]*$")
            try self.validate(self.trustAnchor, name: "trustAnchor", parent: name, max: 20000)
            try self.validate(self.trustAnchor, name: "trustAnchor", parent: name, pattern: "^[a-zA-Z0-9+-/=\\s]*$")
        }

        private enum CodingKeys: String, CodingKey {
            case clusterId = "ClusterId"
            case signedCert = "SignedCert"
            case trustAnchor = "TrustAnchor"
        }
    }

    public struct InitializeClusterResponse: AWSDecodableShape {
        /// The cluster's state.
        public let state: ClusterState?
        /// A description of the cluster's state.
        public let stateMessage: String?

        @inlinable
        public init(state: ClusterState? = nil, stateMessage: String? = nil) {
            self.state = state
            self.stateMessage = stateMessage
        }

        private enum CodingKeys: String, CodingKey {
            case state = "State"
            case stateMessage = "StateMessage"
        }
    }

    public struct ListTagsRequest: AWSEncodableShape {
        /// The maximum number of tags to return in the response. When there are more tags than the number you specify, the response contains a NextToken value.
        public let maxResults: Int?
        /// The NextToken value that you received in the previous response. Use this value to get more tags.
        public let nextToken: String?
        /// The cluster identifier (ID) for the cluster whose tags you are getting. To find the cluster ID, use DescribeClusters.
        public let resourceId: String

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil, resourceId: String) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.resourceId = resourceId
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 256)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: ".*")
            try self.validate(self.resourceId, name: "resourceId", parent: name, pattern: "^(?:cluster|backup)-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case resourceId = "ResourceId"
        }
    }

    public struct ListTagsResponse: AWSDecodableShape {
        /// An opaque string that indicates that the response contains only a subset of tags. Use this value in a subsequent ListTags request to get more tags.
        public let nextToken: String?
        /// A list of tags.
        public let tagList: [Tag]

        @inlinable
        public init(nextToken: String? = nil, tagList: [Tag]) {
            self.nextToken = nextToken
            self.tagList = tagList
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "NextToken"
            case tagList = "TagList"
        }
    }

    public struct ModifyBackupAttributesRequest: AWSEncodableShape {
        /// The identifier (ID) of the backup to modify. To find the ID of a backup, use the DescribeBackups operation.
        public let backupId: String
        /// Specifies whether the service should exempt a backup from the retention policy for the cluster. True exempts  a backup from the retention policy. False means the service applies the backup retention policy defined at the cluster.
        public let neverExpires: Bool

        @inlinable
        public init(backupId: String, neverExpires: Bool) {
            self.backupId = backupId
            self.neverExpires = neverExpires
        }

        public func validate(name: String) throws {
            try self.validate(self.backupId, name: "backupId", parent: name, pattern: "^backup-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case backupId = "BackupId"
            case neverExpires = "NeverExpires"
        }
    }

    public struct ModifyBackupAttributesResponse: AWSDecodableShape {
        public let backup: Backup?

        @inlinable
        public init(backup: Backup? = nil) {
            self.backup = backup
        }

        private enum CodingKeys: String, CodingKey {
            case backup = "Backup"
        }
    }

    public struct ModifyClusterRequest: AWSEncodableShape {
        /// A policy that defines how the service retains backups.
        public let backupRetentionPolicy: BackupRetentionPolicy?
        /// The identifier (ID) of the cluster that you want to modify. To find the cluster ID, use DescribeClusters.
        public let clusterId: String
        /// The desired HSM type of the cluster.
        public let hsmType: String?

        @inlinable
        public init(backupRetentionPolicy: BackupRetentionPolicy? = nil, clusterId: String, hsmType: String? = nil) {
            self.backupRetentionPolicy = backupRetentionPolicy
            self.clusterId = clusterId
            self.hsmType = hsmType
        }

        public func validate(name: String) throws {
            try self.backupRetentionPolicy?.validate(name: "\(name).backupRetentionPolicy")
            try self.validate(self.clusterId, name: "clusterId", parent: name, pattern: "^cluster-[2-7a-zA-Z]{11,16}$")
            try self.validate(self.hsmType, name: "hsmType", parent: name, max: 32)
            try self.validate(self.hsmType, name: "hsmType", parent: name, pattern: "^((p|)hsm[0-9][a-z.]*\\.[a-zA-Z]+)$")
        }

        private enum CodingKeys: String, CodingKey {
            case backupRetentionPolicy = "BackupRetentionPolicy"
            case clusterId = "ClusterId"
            case hsmType = "HsmType"
        }
    }

    public struct ModifyClusterResponse: AWSDecodableShape {
        public let cluster: Cluster?

        @inlinable
        public init(cluster: Cluster? = nil) {
            self.cluster = cluster
        }

        private enum CodingKeys: String, CodingKey {
            case cluster = "Cluster"
        }
    }

    public struct PutResourcePolicyRequest: AWSEncodableShape {
        /// The policy you want to associate with a resource.  For an example policy, see  Working with shared backups in the CloudHSM User Guide
        public let policy: String?
        /// Amazon Resource Name (ARN) of the resource to which you want to attach a policy.
        public let resourceArn: String?

        @inlinable
        public init(policy: String? = nil, resourceArn: String? = nil) {
            self.policy = policy
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.policy, name: "policy", parent: name, max: 20000)
            try self.validate(self.policy, name: "policy", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws(-(us-gov))?:cloudhsm:([a-z]{2}(-(gov|isob|iso))?-(east|west|north|south|central){1,2}-[0-9]{1}):[0-9]{12}:(backup/backup|cluster/cluster|hsm/hsm)-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case resourceArn = "ResourceArn"
        }
    }

    public struct PutResourcePolicyResponse: AWSDecodableShape {
        /// The policy attached to a resource.
        public let policy: String?
        /// Amazon Resource Name (ARN) of the resource to which a policy is attached.
        public let resourceArn: String?

        @inlinable
        public init(policy: String? = nil, resourceArn: String? = nil) {
            self.policy = policy
            self.resourceArn = resourceArn
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case resourceArn = "ResourceArn"
        }
    }

    public struct RestoreBackupRequest: AWSEncodableShape {
        /// The ID of the backup to be restored. To find the ID of a backup, use the DescribeBackups operation.
        public let backupId: String

        @inlinable
        public init(backupId: String) {
            self.backupId = backupId
        }

        public func validate(name: String) throws {
            try self.validate(self.backupId, name: "backupId", parent: name, pattern: "^backup-[2-7a-zA-Z]{11,16}$")
        }

        private enum CodingKeys: String, CodingKey {
            case backupId = "BackupId"
        }
    }

    public struct RestoreBackupResponse: AWSDecodableShape {
        /// Information on the Backup object created.
        public let backup: Backup?

        @inlinable
        public init(backup: Backup? = nil) {
            self.backup = backup
        }

        private enum CodingKeys: String, CodingKey {
            case backup = "Backup"
        }
    }

    public struct Tag: AWSEncodableShape & AWSDecodableShape {
        /// The key of the tag.
        public let key: String
        /// The value of the tag.
        public let value: String

        @inlinable
        public init(key: String, value: String) {
            self.key = key
            self.value = value
        }

        public func validate(name: String) throws {
            try self.validate(self.key, name: "key", parent: name, max: 128)
            try self.validate(self.key, name: "key", parent: name, min: 1)
            try self.validate(self.key, name: "key", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$")
            try self.validate(self.value, name: "value", parent: name, max: 256)
            try self.validate(self.value, name: "value", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$")
        }

        private enum CodingKeys: String, CodingKey {
            case key = "Key"
            case value = "Value"
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        /// The cluster identifier (ID) for the cluster that you are tagging. To find the cluster ID, use DescribeClusters.
        public let resourceId: String
        /// A list of one or more tags.
        public let tagList: [Tag]

        @inlinable
        public init(resourceId: String, tagList: [Tag]) {
            self.resourceId = resourceId
            self.tagList = tagList
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceId, name: "resourceId", parent: name, pattern: "^(?:cluster|backup)-[2-7a-zA-Z]{11,16}$")
            try self.tagList.forEach {
                try $0.validate(name: "\(name).tagList[]")
            }
            try self.validate(self.tagList, name: "tagList", parent: name, max: 50)
            try self.validate(self.tagList, name: "tagList", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case resourceId = "ResourceId"
            case tagList = "TagList"
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        /// The cluster identifier (ID) for the cluster whose tags you are removing. To find the cluster ID, use DescribeClusters.
        public let resourceId: String
        /// A list of one or more tag keys for the tags that you are removing. Specify only the tag keys, not the tag values.
        public let tagKeyList: [String]

        @inlinable
        public init(resourceId: String, tagKeyList: [String]) {
            self.resourceId = resourceId
            self.tagKeyList = tagKeyList
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceId, name: "resourceId", parent: name, pattern: "^(?:cluster|backup)-[2-7a-zA-Z]{11,16}$")
            try self.tagKeyList.forEach {
                try validate($0, name: "tagKeyList[]", parent: name, max: 128)
                try validate($0, name: "tagKeyList[]", parent: name, min: 1)
                try validate($0, name: "tagKeyList[]", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$")
            }
            try self.validate(self.tagKeyList, name: "tagKeyList", parent: name, max: 50)
            try self.validate(self.tagKeyList, name: "tagKeyList", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case resourceId = "ResourceId"
            case tagKeyList = "TagKeyList"
        }
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }
}

// MARK: - Errors

/// Error enum for CloudHSMV2
public struct CloudHSMV2ErrorType: AWSErrorType {
    enum Code: String {
        case cloudHsmAccessDeniedException = "CloudHsmAccessDeniedException"
        case cloudHsmInternalFailureException = "CloudHsmInternalFailureException"
        case cloudHsmInvalidRequestException = "CloudHsmInvalidRequestException"
        case cloudHsmResourceLimitExceededException = "CloudHsmResourceLimitExceededException"
        case cloudHsmResourceNotFoundException = "CloudHsmResourceNotFoundException"
        case cloudHsmServiceException = "CloudHsmServiceException"
        case cloudHsmTagException = "CloudHsmTagException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize CloudHSMV2
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// The request was rejected because the requester does not have permission to perform the requested operation.
    public static var cloudHsmAccessDeniedException: Self { .init(.cloudHsmAccessDeniedException) }
    /// The request was rejected because of an CloudHSM internal failure. The request can be retried.
    public static var cloudHsmInternalFailureException: Self { .init(.cloudHsmInternalFailureException) }
    /// The request was rejected because it is not a valid request.
    public static var cloudHsmInvalidRequestException: Self { .init(.cloudHsmInvalidRequestException) }
    /// The request was rejected because it exceeds an CloudHSM limit.
    public static var cloudHsmResourceLimitExceededException: Self { .init(.cloudHsmResourceLimitExceededException) }
    /// The request was rejected because it refers to a resource that cannot be found.
    public static var cloudHsmResourceNotFoundException: Self { .init(.cloudHsmResourceNotFoundException) }
    /// The request was rejected because an error occurred.
    public static var cloudHsmServiceException: Self { .init(.cloudHsmServiceException) }
    /// The request was rejected because of a tagging failure. Verify the tag conditions in all applicable policies, and then retry the request.
    public static var cloudHsmTagException: Self { .init(.cloudHsmTagException) }
}

extension CloudHSMV2ErrorType: Equatable {
    public static func == (lhs: CloudHSMV2ErrorType, rhs: CloudHSMV2ErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension CloudHSMV2ErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
